package com.sjz.controller;

import com.sjz.po.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;

/*****
 1、对于处理指定请求方式的控制器方法，SpringMVC中提供了@RequestMapping的派生注解
 处理get请求的映射-->@GetMapping
 处理post请求的映射-->@PostMapping
 处理put请求的映射-->@PutMapping
 处理delete请求的映射-->@DeleteMapping
 2、常用的请求方式有get，post，put，delete
 但是目前浏览器只支持get和post，若在form表单提交时，为method设置了其他请求方式的字符
 串（put或delete），则按照默认的请求方式get处理
 若要发送put和delete请求，则需要通过spring提供的过滤器HiddenHttpMethodFilter，在
 RESTful部分会讲到
 "param"：要求请求映射所匹配的请求必须携带param请求参数
 "!param"：要求请求映射所匹配的请求必须不能携带param请求参数
 "param=value"：要求请求映射所匹配的请求必须携带param请求参数且param=value
 "param!=value"：要求请求映射所匹配的请求必须携带param请求参数但是param!=value

 "header"：要求请求映射所匹配的请求必须携带header请求头信息
 "!header"：要求请求映射所匹配的请求必须不能携带header请求头信息
 "header=value"：要求请求映射所匹配的请求必须携带header请求头信息且header=value
 "header!=value"：要求请求映射所匹配的请求必须携带header请求头信息且header!=value

 */
@Controller
public class HelloWorldController {

    // @RequestMapping注解：处理请求和控制器方法之间的映射关系
// @RequestMapping注解的value属性可以通过请求地址匹配请求，/表示的当前工程的上下文路径
// localhost:8080/springMVC/

    @RequestMapping("/")
    public String index() {
        return "index";
    }

    @RequestMapping("/hello")
    public String HelloWorld() {
        System.out.println("helloworld..............");
        return "success";
    }

    @RequestMapping(
            value = {"/testRequestMapping", "/test"},
            method = {RequestMethod.POST,RequestMethod.GET}
            ,params = {"password=123456","!username"}
        )
    public String testRequestMapping() {
        System.out.println("hello  world");
        return "success";
    }

    @RequestMapping("/testRest/{id}/{username}")
    public String testRest(@PathVariable("id") String id, @PathVariable("username")
            String username){
        System.out.println("id:"+id+",username:"+username);
        return "success";
    }
//最终输出的内容为-->id:1,username:admin

    /****
     * 将HttpServletRequest作为控制器方法的形参，此时HttpServletRequest类型的参数表示封装了当前请
     * 求的请求报文的对象
     * @param request
     * @return
     */
    @RequestMapping("/testParam1")
    public String testParam1(HttpServletRequest request){
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("username:"+username+",password:"+password);
        return "success";
    }

    /****
     * 在控制器方法的形参位置，设置和请求参数同名的形参，当浏览器发送请求，匹配到请求映射时，在
     * DispatcherServlet中就会将请求参数赋值给相应的形参
     * @param username
     * @param password
     * @return
     */
    @RequestMapping("/testPara1")
    public String testParam1(String username, String password){
        System.out.println("username1:"+username+",password1:"+password);
        return "success";
    }

    /*****
     * @RequestParam是将请求参数和控制器方法的形参创建映射关系
     * @RequestParam注解一共有三个属性：
     * value：指定为形参赋值的请求参数的参数名
     * required：设置是否必须传输此请求参数，默认值为true
     * 若设置为true时，则当前请求必须传输value所指定的请求参数，若没有传输该请求参数，且没有设置
     * defaultValue属性，则页面报错400：Required String parameter 'xxx' is not present；若设置为
     * false，则当前请求不是必须传输value所指定的请求参数，若没有传输，则注解所标识的形参的值为
     * null
     * defaultValue：不管required属性值为true或false，当value所指定的请求参数没有传输或传输的值
     * 为""时，则使用默认值为形参赋值
     * 传的参数和接收的参数不一致  可以使用@RequestParam来进行映射
     *
     * @RequestHeader是将请求头信息和控制器方法的形参创建映射关系
     * @RequestHeader注解一共有三个属性：value、required、defaultValue，用法同@RequestParam
     * @param name
     * @param password
     * @return
     */
    @RequestMapping("/testParam")
    public String testParam(@RequestParam(value = "username", required = true, defaultValue = "hello") String name,
                            String password,
                            @RequestHeader("referer") String referer
                            ){
        System.out.println("referer:"+referer);    //referer:http://localhost:8080/springmvc/
        System.out.println("username1:"+name+",password1:"+password);
        return "success";
    }

    /****
     * 实体接收参数
     * @param user
     * @return
     */
    @RequestMapping("/param/pojo")
    public String getParamByPojo(User user){
        System.out.println(user);
        return "success";
    }

    /****
     * 使用ServletAPI向request域对象共享数据
     * @param request
     * @return
     */
    @RequestMapping("/testServletAPI")
    public String testServletAPI(HttpServletRequest request){
        request.setAttribute("testScope", "hello,servletAPI");
        return "success";
    }

    /****
     * 使用ModelAndView向request域对象共享数据
     * @return
     */
    @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView(){
        /**
         * ModelAndView有Model和View的功能
         * Model主要用于向请求域共享数据
         * View主要用于设置视图，实现页面跳转
         */
                ModelAndView mav = new ModelAndView();
               //向请求域共享数据
                mav.addObject("testScope", "hello,ModelAndView");
        //设置视图，实现页面跳转
                mav.setViewName("success");
                return mav;
    }

    /****
     * 使用Model向request域对象共享数据
     * @param model
     * @return
     */
    @RequestMapping("/testModel")
    public String testModel(Model model){
        model.addAttribute("testScope", "hello,Model");
        return "success";
    }

    /****
     * 使用map向request域对象共享数据
     * @param map
     * @return
     */
    @RequestMapping("/testMap")
    public String testMap(Map<String, Object> map){
        System.out.println("testMap");
        map.put("testScope", "hello,Map");
        return "success";
    }

    /****
     *
     * 使用ModelMap向request域对象共享数据
     * @param modelMap
     * @return
     */
    @RequestMapping("/testModelMap")
    public String testModelMap(ModelMap modelMap){
        modelMap.addAttribute("testScope", "hello,ModelMap");
        return "success";
    }

    /*****
     Model、ModelMap、Map的关系
     Model、ModelMap、Map类型的参数其实本质上都是 BindingAwareModelMap 类型的
     public interface Model{}
     public class ModelMap extends LinkedHashMap<String, Object> {}
     public class ExtendedModelMap extends ModelMap implements Model {}
     public class BindingAwareModelMap extends ExtendedModelMap {}
     */

    /****
     * 向session域共享数据
     * @param session
     * @return
     */
    @RequestMapping("/testSession")
    public String testSession(HttpSession session){
        System.out.println("testSession");
        session.setAttribute("testSessionScope", "hello,session");
        return "success";
    }

    /***
     * 向application域共享数据
     * @param session
     * @return
     */
    @RequestMapping("/testApplication")
    public String testApplication(HttpSession session){
        System.out.println("testApplication");
        ServletContext application = session.getServletContext();
        application.setAttribute("testApplicationScope", "hello,application");
        return "success";
    }

    @RequestMapping("/testHello")
    public String testHello(){
        return "hello";
    }

    /****
     * 转发视图
     * @return
     */
    @RequestMapping("/testForward")
    public String testForward(){
        System.out.println("testForward");
        return "forward:/testHello";
    }


    /****
     * 重定向视图
     * @return
     */
    @RequestMapping("/testRedirect")
    public String testRedirect(){
        return "redirect:/testHello";
    }


}
